package com.mygame

import com.almasb.fxgl.dsl.*
import com.almasb.fxgl.dsl.components.*
import com.almasb.fxgl.entity.*
import com.almasb.fxgl.entity.components.IDComponent
import com.almasb.fxgl.entity.state.StateComponent
import com.almasb.fxgl.pathfinding.CellMoveComponent
import com.almasb.fxgl.pathfinding.astar.AStarGrid
import com.almasb.fxgl.pathfinding.astar.AStarMoveComponent
import com.almasb.fxgl.physics.BoundingShape
import com.mygame.components.*
import javafx.geometry.Point2D
import javafx.scene.paint.Color
import javafx.scene.shape.Circle
import javafx.scene.shape.Rectangle
import javafx.scene.text.Text
import java.util.*


class MyEntityFactory : EntityFactory {

    fun init() {
        FXGL.getGameWorld().addEntityFactory(this)
    }

    @Spawns("player2")//孵化器名称
    fun player2Create(data: SpawnData): Entity {
        val d = data.get<Double>(Const.RADIUS)

        val mp = data.get<Int>(Const.MANA)
        val hpEntity =
            spawn(EType.HP, SpawnData(0.0, -50.0).put(Const.RADIUS, d).put(Const.HEALTH, data.get<Int>(Const.HEALTH)))

        val entity = entityBuilder(data)//新建entity,万物皆entity
            .type(EType.PLAYER2)//挂一个类型,提供给碰撞攻击等使用
            .bbox(BoundingShape.box(d, d))//矩形碰撞体
            .with(Const.HP_ENTITY, hpEntity)//挂一个其他的entity,这里是血条
            .collidable()//可碰撞
            .with(StateComponent())//挂一个状态Component,给下面PlayerStateComponent去判断当前是攻击还是站立
            .with(PlayerStateComponent())//包含攻击/站立/跑/跳等状态
            .with(ComboComponent())//搓招Component ←→←
            .with(PlayerControllerComponent())//上下左右的控制Component
            .with(IDComponent(EType.PLAYER.name, 1))//加一个id,暂时没用
            .with(ManaIntComponent(mp))//魔法值Component,暂时没用
            .build()
        hpEntity.xProperty().bind(entity.xProperty())//血条挂在player的相对位置,会跟着跑
        hpEntity.yProperty().bind(entity.yProperty())
        println("player2.center=${entity.center}   position=${entity.position}   anchoredPosition=${entity.anchoredPosition} ")
        return entity
    }

    @Spawns("hp")
    fun hpCreate(data: SpawnData): Entity {
        val d = data.get<Double>(Const.RADIUS)
        val height = 5.0
        val hpMax = Rectangle(0.0, data.y, d, height)
        val hp = data.get<Int>(Const.HEALTH)
        val hpComponent = HealthIntComponent(hp)
        val hpNow = Rectangle(0.0, data.y, d * hpComponent.value / hp, height)
        hpNow.fill = Color.RED
        return entityBuilder(data)
            .view(hpMax)
            .view(hpNow)
            .with(hpComponent)
            .build()
    }

    @Spawns("player")
    fun playerCreate(data: SpawnData): Entity {
        val d = data.get<Double>(Const.RADIUS)
        val barrel = spawn(EType.BARREL, SpawnData(data.x, data.y).put(Const.RADIUS, d))
        val rect1 = Rectangle(d, d / 3, data.get(Const.COLOR))
        val rect2 = Rectangle(d * 0.9, d / 3, Color.DARKBLUE)
        rect2.y = d / 3
        val rect3 = Rectangle(d, d / 3, data.get(Const.COLOR))
        rect3.y = d * 2 / 3

        val mp = data.get<Int>(Const.MANA)
        val hpEntity =
            spawn(EType.HP, SpawnData(0.0, -20.0).put(Const.RADIUS, d).put(Const.HEALTH, data.get<Int>(Const.HEALTH)))

        val entity = entityBuilder(data)
            .type(EType.PLAYER)
            .view(rect1)
            .view(rect2)
            .view(rect3)
            .bbox(BoundingShape.box(d, d))
            .with(Const.WIDGET_ENTITY, barrel)
            .with(Const.HP_ENTITY, hpEntity)
            //.viewWithBBox(Circle(r, r, r, data.get("color")))
            //.bbox(BoundingShape.box(data.get("r"), data.get("r")))
            .collidable()
            .with(ComboComponent())
            .with(ControllerComponent())
            .with(IDComponent(EType.PLAYER.name, 1))
            .with(ManaIntComponent(mp))
            .build()
        //barrel层级要往上提,才不会遮盖
        barrel.zIndex = entity.zIndex + 1
        //barrel的坐标绑定到entity上
        barrel.xProperty().bind(entity.xProperty())
        barrel.yProperty().bind(entity.yProperty())

        hpEntity.xProperty().bind(entity.xProperty())
        hpEntity.yProperty().bind(entity.yProperty())
        //println("entity->" + entity.x + "," + entity.y + ",entity->" + entity.center + "  rotation:" + entity.rotation)
        return entity
    }

    @Spawns("enemy")
    fun newEnemy(data: SpawnData): Entity {


        var r = data.get<Double>(Const.RADIUS)
        var outR = r * 2
        //炮筒
        val rect = Rectangle(r, r - 5, r, 10.0)
        //炮筒颜色
        rect.fill = Color.RED
        val innerCircle = Circle(r, r, r, data.get(Const.COLOR))
        val outerCircle = Circle(r, r, outR, Color(0.8, 0.078, 0.23, 0.1))
        //val innerBox = HitBox(Point2D.ZERO, BoundingShape.circle(outR))
        //val outerBox = HitBox("view_hit", Point2D(-outR + r, -outR + r), BoundingShape.circle(outR))

        val hpEntity =
            spawn(EType.HP, SpawnData(0.0, -r).put(Const.RADIUS, r).put(Const.HEALTH, data.get<Int>(Const.HEALTH)))

        val entity = entityBuilder(data)
            .type(EType.ENEMY)
            .viewWithBBox(innerCircle)
            //.bbox(innerBox)
            .collidable()
            .view(outerCircle)
            //.bbox(outerBox)
            .view(rect)
            //.with(HuntTagComponent())
            .with(Const.HP_ENTITY, hpEntity)//挂一个其他的entity,这里是血条
            .with(StateComponent())
            .with(CellMoveComponent(Const.CELL_WIDTH, Const.CELL_HEIGHT, 60.0))
            .with(AStarMoveComponent(data.get(Const.GRID) as AStarGrid))
            .with(NearEntityComponent())//必须放在最下面
            //.with(CustomAIComponent())
            //.with(PathAIComponent())
            .build()

        hpEntity.xProperty().bind(entity.xProperty())//血条挂在player的相对位置,会跟着跑
        hpEntity.yProperty().bind(entity.yProperty())

        //entity.setPosition(entity.x + entity.width / 2, entity.y + entity.height / 2)
        entity.setLocalAnchorFromCenter()
        println("1entity.center=${entity.center}   position=${entity.position}   anchoredPosition=${entity.anchoredPosition} ")
        return entity
    }

    @Spawns("enemy2")
    fun newEnemy3(data: SpawnData): Entity {
        var d = data.get<Double>(Const.RADIUS)
        val rect1 = Rectangle(d, d / 3, data.get(Const.COLOR))
        val rect2 = Rectangle(d * 0.9, d / 3, Color.DARKCYAN)
        rect2.y = d / 3
        val rect3 = Rectangle(d, d / 3, data.get(Const.COLOR))
        rect3.y = d * 2 / 3
        val entity = entityBuilder(data)
            .type(EType.ENEMY)
            .view(rect1)
            .view(rect2)
            .view(rect3)
            .bbox(BoundingShape.box(d, d))
            //.with(BoundingBoxComponent(HitBox(Point2D(d/2 , d / 2), BoundingShape.box(d, d))))
            .collidable()
            .with(CellMoveComponent(Const.CELL_WIDTH, Const.CELL_HEIGHT, 60.0))
            .with(AStarMoveComponent(data.get(Const.GRID) as AStarGrid))
            .with(NearEntityComponent())//必须放在最下面
            //.with(CustomAIComponent())
            .build()
        println("3entity.center=${entity.center}   position=${entity.position}   rotation=${entity.rotationZProperty()} ")
        return entity
    }

    @Spawns("barrel")
    fun barrelCreate(data: SpawnData): Entity {
        var d = data.get<Double>(Const.RADIUS)
        val height = 10.0
        //炮筒位置
        val x = d / 2
        val y = d / 2 - height / 2
        //炮筒
        val rect = Rectangle(x, y, d, height)
        //炮筒颜色
        rect.fill = Color.RED
        rect.userData = "barrel"
        val entity = entityBuilder(data)
            .view(rect)
            .buildAndAttach()
        //旋转的中心点(设置靠左边中间位置)
        entity.setRotationOrigin(Point2D(x, d / 2))
        return entity
    }

    @Spawns("bullet")
    fun newBullet(data: SpawnData): Entity {
        var r = data.get<Double>(Const.RADIUS)
        val entity = entityBuilder(data)
            .type(EType.BULLET)
            .viewWithBBox(Circle(r, r, r, data.get(Const.COLOR)))
            //.bbox(BoundingShape.box(data.get("r"), data.get("r")))
            .with(ProjectileComponent(data.get(Const.DIR), data.get(Const.SPEED)))
            .with(OffscreenCleanComponent())
            .collidable()
            .buildAndAttach()
        //println("BULLET->" + entity.x + "," + entity.y + ",entity->" + entity.center)
        return entity
    }

    @Spawns("camara")
    fun camaraCreate(data: SpawnData): Entity {
        val camera = Entity()
        val tagEntity = data.get<Entity>(Const.TAG_ENTITY)
        camera.addComponent(FollowComponent(tagEntity))
        getGameWorld().addEntity(camera)
        getGameScene().viewport.bindToEntity(
            tagEntity,
            tagEntity.center.x - tagEntity.width,
            tagEntity.center.y - tagEntity.height
        )
        //getGameScene().viewport.isLazy = true
        return camera
    }

    @Spawns("wall")
    fun wallCreate(data: SpawnData): Entity {
        val t = Text("${data.data}")
        return entityBuilder(data)
            .type(EType.WALL)
            //.view(t)
            .viewWithBBox(Rectangle(data.get(Const.WIDTH), data.get(Const.HEIGHT), Color.RED))
            .build()
    }

    @Spawns("ground")
    fun groundCreate(data: SpawnData): Entity {
        val w = data.get<Double>(Const.WIDTH)
        val h = data.get<Double>(Const.HEIGHT)
        val rect1 = Rectangle(w, h, data.get(Const.COLOR))
        val entity = entityBuilder(data)
            .view(rect1)
            .build()
        entity.zIndex = -1
        return entity
    }

    @Spawns("path")
    fun pathCreate(data: SpawnData): Entity {
        val w = data.get<Double>(Const.WIDTH)
        val h = data.get<Double>(Const.HEIGHT)
        val rect = Rectangle(w, h, data.get(Const.COLOR))
        val entity = entityBuilder(data)
            .type(EType.PATH)
            .viewWithBBox(rect)
            .collidable()
            .build()
        entity.setLocalAnchorFromCenter()
        println("path.center=${entity.center}   position=${entity.position}   anchoredPosition=${entity.anchoredPosition} ")
        return entity
    }


    /*@Spawns("A")
    fun newA(data: SpawnData?): Entity? {
        // 这里就是设置方块的物理属性，设置密度，能在物理世界自由下坠
        val physics = PhysicsComponent()
        physics.setBodyType(BodyType.DYNAMIC)
        physics.setFixtureDef(FixtureDef().density(0.00f))
        return entityBuilder(data!!)
            .viewWithBBox(Circle(data.get(Const.RADIUS), data.get(Const.COLOR)))
            .with(HealthIntComponent(2))
            .with(physics)
            .collidable()
            .build()
    }*/
}